﻿Imports System.Collections.Generic
Imports System.Text
Imports System.Windows.Controls
Imports System.Windows
Imports System.Collections
Imports System.ComponentModel
Imports System.Windows.Data
Imports System.Windows.Media

' if the GridView exposed any methods at all that allowed for overriding at a control level, I would be
' able to do all of this work inside it rather than the ListView. However, b/c it doesn't, I have to do the 
' work inside the ListView.

' The GridView has access to the ItemSource on the ListView through the dependency property mechanism.

Public Class SortableListView
    Inherits ListView
    ' The current column that is sorted.
    Private sortColumn As SortListViewColumn

    ' The previous column that was sorted.
    Private previousSortColumn As SortListViewColumn

    ' The current direction the header is sorted;
    Private sortDirection As ListSortDirection

    Protected Overrides Sub OnInitialized(ByVal e As EventArgs)
        ' Handle the event when a header is clicked.
        Me.[AddHandler](GridViewColumnHeader.ClickEvent, New RoutedEventHandler(AddressOf OnHeaderClicked))
        MyBase.OnInitialized(e)
    End Sub

    ''' <summary>
    ''' A header was clicked. Sort the associated column.
    ''' </summary>
    Private Sub OnHeaderClicked(ByVal sender As Object, ByVal e As RoutedEventArgs)
        ' Make sure the column is really being sorted.
        Dim header As GridViewColumnHeader = TryCast(e.OriginalSource, GridViewColumnHeader)
        If header Is Nothing OrElse header.Role = GridViewColumnHeaderRole.Padding Then
            Return
        End If

        Dim column As SortListViewColumn = TryCast(header.Column, SortListViewColumn)
        If column Is Nothing Then
            Return
        End If

        ' See if a new column was clicked, or the same column was clicked.
        If Not sortColumn.Equals(column) Then
            ' A new column was clicked.
            previousSortColumn = sortColumn
            sortColumn = column
            sortDirection = ListSortDirection.Ascending
        Else
            ' The same column was clicked, change the sort order.
            previousSortColumn = Nothing
            sortDirection = If((sortDirection = ListSortDirection.Ascending), ListSortDirection.Descending, ListSortDirection.Ascending)
        End If

        ' Sort the data.
        SortList(column.SortProperty)

        ' Update the column header based on the sort column and order.
        UpdateHeaderTemplate()
    End Sub

    ''' <summary>
    ''' Sort the data.
    ''' </summary>
    Private Sub SortList(ByVal propertyName As String)
        Try
            ' Get the data to sort.
            Dim dataView As ICollectionView = CollectionViewSource.GetDefaultView(Me.ItemsSource)

            ' Specify the new sorting information.
            dataView.SortDescriptions.Clear()
            Dim description As New SortDescription(propertyName, sortDirection)
            dataView.SortDescriptions.Add(description)

            dataView.Refresh()
        Catch
        End Try
    End Sub

    ''' <summary>
    ''' Update the column header based on the sort column and order.
    ''' </summary>
    Private Sub UpdateHeaderTemplate()
        Dim headerStyle As Style

        ' Restore the previous header.
        If previousSortColumn IsNot Nothing AndAlso previousSortColumn.SortStyle IsNot Nothing Then
            headerStyle = TryCast(Me.TryFindResource(previousSortColumn.SortStyle), Style)
            If headerStyle IsNot Nothing Then
                previousSortColumn.HeaderContainerStyle = headerStyle
            End If
        End If

        ' Update the current header.
        If sortColumn.SortStyle IsNot Nothing Then
            ' The name of the resource to use for the header.
            Dim resourceName As String = Convert.ToString(sortColumn.SortStyle) & sortDirection.ToString()

            headerStyle = TryCast(Me.TryFindResource(resourceName), Style)
            If headerStyle IsNot Nothing Then
                sortColumn.HeaderContainerStyle = headerStyle
            End If
        End If
    End Sub
End Class

